#ifndef Error_h
#define Error_h


class Error_T
{
public:
	enum Code_T
	{
		ERR_NONE,						// No Error

		ERR_REQUEST_FORMAT,				// Malformed request

		ERR_VERB_ALLOWED,				// Allowed verb not found in Url
		ERR_VERB_DENIED,				// Denied verb '%s' found in Url

		ERR_SCHEMA_FORMAT,				// Unallowed host:port pair found in schema
		ERR_URL_MAXLEN,					// Url exceeds allowed length
		ERR_URL_FIRSTBYTE,				// Invalid character found at start of Url
		ERR_URL_CANON_CHANGE,			// Url different after 2nd canon
		ERR_URL_DOT_NOEXT,				// Dot found in Url before extension
		ERR_URL_EXTALLOWED,				// Allowed extension not found in Url
		ERR_URL_EXTDENIED,				// Denied extension '%s' found in Url
		ERR_URL_HIGHBIT,				// High bit character found in Url
		ERR_URL_CTL,					// Control character (< 0x20) found in Url
		ERR_URL_SEQ,					// Unallowed sequence '%s' found in Url

		ERR_QUERY_SEQ,					// Unallowed sequence '%s' found in Query
		ERR_QUERY_HIGHBIT,				// High bit character found in Query
		ERR_QUERY_CTL,					// Control character (< 0x20) found in Query
		ERR_QUERY_MAXLEN,				// Query exceeds allowed length
		ERR_QUERY_CANON_CHANGE,			// Query different after 2nd canon

		ERR_VERSION_FORMAT,				// Unallowed http version

		ERR_HEADER_NOCOLON,				// Header separator (':') not found
		ERR_HEADERNAME_MAXLEN,			// Header name exceeds allowed length
		ERR_HEADERVALUE_MAXLEN,			// Header value exceeds allowed length
		ERR_HEADERNAME_FORMAT,			// Unallowed byte found in header name
		ERR_HEADERVALUE_FORMAT,			// Unallowed byte found in header value
		ERR_HEADER_FORMAT,				// Unallowed header name '%s'
		ERR_HEADER_HOST,				// Unallowed pair host:port found in host header

		ERR_HEADER_CONTENTLENGTH,		// Content-Length header was sent incorrectly
		ERR_CONTENTHEADER_MAXVALUE,		// Content-Length header exceeded maximum value allowed
		ERR_MAXLENBYHEADER,				// Request header '%s' value exceeds allowed length

		ERR_PAYLOAD_MAXLEN,				// Payload exceeds allowed length
		ERR_PAYLOAD_HIGHBIT,			// High bit character found in Payload

		ERR_WINDOWS						// Windows returned an error
	};

	Error_T(const Code_T & code)
		:_code(code)
		,_dwErr(NO_ERROR)
	{
		SetDescription();
	}

	Error_T(DWORD dwErr)
		:_code(ERR_WINDOWS)
		,_dwErr(dwErr)
	{
		SetDescription();
	}

	Error_T(const Code_T & code, DWORD dwErr)
		:_code(code)
		,_dwErr(dwErr)
	{
		SetDescription();
	}

	const Code_T Code() const { return _code; }
	const DWORD WinErr() const { return _dwErr; }
	const char * ToString() const { return _szText; }

private:
	Code_T _code;
	DWORD _dwErr;
	char _szText[50];

	void SetDescription()
	{
		FillMemory(_szText, sizeof(_szText), 0);

		switch( _code )
		{
			case ERR_NONE:						_snprintf(_szText, sizeof(_szText) - 1, TXT_ERR_NONE); break;
			case ERR_REQUEST_FORMAT:			_snprintf(_szText, sizeof(_szText) - 1, TXT_ERR_REQUEST_FORMAT); break;
			case ERR_VERB_ALLOWED:				_snprintf(_szText, sizeof(_szText) - 1, TXT_ERR_VERB_ALLOWED); break;
			case ERR_VERB_DENIED:				_snprintf(_szText, sizeof(_szText) - 1, TXT_ERR_VERB_DENIED); break;
			case ERR_SCHEMA_FORMAT:				_snprintf(_szText, sizeof(_szText) - 1, TXT_ERR_SCHEMA_FORMAT); break;
			case ERR_URL_MAXLEN:				_snprintf(_szText, sizeof(_szText) - 1, TXT_ERR_URL_MAXLEN); break;
			case ERR_URL_FIRSTBYTE:				_snprintf(_szText, sizeof(_szText) - 1, TXT_ERR_URL_FIRSTBYTE); break;
			case ERR_URL_CANON_CHANGE:			_snprintf(_szText, sizeof(_szText) - 1, TXT_ERR_URL_CANON_CHANGE); break;
			case ERR_URL_DOT_NOEXT:				_snprintf(_szText, sizeof(_szText) - 1, TXT_ERR_URL_DOT_NOEXT); break;
			case ERR_URL_EXTALLOWED:			_snprintf(_szText, sizeof(_szText) - 1, TXT_ERR_URL_EXTALLOWED); break;
			case ERR_URL_EXTDENIED:				_snprintf(_szText, sizeof(_szText) - 1, TXT_ERR_URL_EXTDENIED); break;
			case ERR_URL_HIGHBIT:				_snprintf(_szText, sizeof(_szText) - 1, TXT_ERR_URL_HIGHBIT); break;
			case ERR_URL_CTL:					_snprintf(_szText, sizeof(_szText) - 1, TXT_ERR_URL_CTL); break;
			case ERR_URL_SEQ:					_snprintf(_szText, sizeof(_szText) - 1, TXT_ERR_URL_SEQ); break;
			case ERR_QUERY_SEQ:					_snprintf(_szText, sizeof(_szText) - 1, TXT_ERR_QUERY_SEQ); break;
			case ERR_QUERY_HIGHBIT:				_snprintf(_szText, sizeof(_szText) - 1, TXT_ERR_QUERY_HIGHBIT); break;
			case ERR_QUERY_CTL:					_snprintf(_szText, sizeof(_szText) - 1, TXT_ERR_QUERY_CTL); break;
			case ERR_QUERY_MAXLEN:				_snprintf(_szText, sizeof(_szText) - 1, TXT_ERR_QUERY_MAXLEN); break;
			case ERR_QUERY_CANON_CHANGE:		_snprintf(_szText, sizeof(_szText) - 1, TXT_ERR_QUERY_CANON_CHANGE); break;
			case ERR_VERSION_FORMAT:			_snprintf(_szText, sizeof(_szText) - 1, TXT_ERR_VERSION_FORMAT); break;
			case ERR_HEADER_NOCOLON:			_snprintf(_szText, sizeof(_szText) - 1, TXT_ERR_HEADER_NOCOLON); break;
			case ERR_HEADERNAME_MAXLEN:			_snprintf(_szText, sizeof(_szText) - 1, TXT_ERR_HEADERNAME_MAXLEN); break;
			case ERR_HEADERVALUE_MAXLEN:		_snprintf(_szText, sizeof(_szText) - 1, TXT_ERR_HEADERVALUE_MAXLEN); break;
			case ERR_HEADERNAME_FORMAT:			_snprintf(_szText, sizeof(_szText) - 1, TXT_ERR_HEADERNAME_FORMAT); break;
			case ERR_HEADERVALUE_FORMAT:		_snprintf(_szText, sizeof(_szText) - 1, TXT_ERR_HEADERVALUE_FORMAT); break;
			case ERR_HEADER_FORMAT:				_snprintf(_szText, sizeof(_szText) - 1, TXT_ERR_HEADER_FORMAT); break;
			case ERR_HEADER_HOST:				_snprintf(_szText, sizeof(_szText) - 1, TXT_ERR_HEADER_HOST); break;
			case ERR_HEADER_CONTENTLENGTH:		_snprintf(_szText, sizeof(_szText) - 1, TXT_ERR_HEADER_CONTENTLENGTH); break;
			case ERR_CONTENTHEADER_MAXVALUE:	_snprintf(_szText, sizeof(_szText) - 1, TXT_ERR_CONTENTHEADER_MAXVALUE); break;
			case ERR_MAXLENBYHEADER:			_snprintf(_szText, sizeof(_szText) - 1, TXT_ERR_MAXLENBYHEADER); break;
			case ERR_PAYLOAD_MAXLEN:			_snprintf(_szText, sizeof(_szText) - 1, TXT_ERR_PAYLOAD_MAXLEN); break;
			case ERR_PAYLOAD_HIGHBIT:			_snprintf(_szText, sizeof(_szText) - 1, TXT_ERR_PAYLOAD_HIGHBIT); break;
			case ERR_WINDOWS:					_snprintf(_szText, sizeof(_szText) - 1, TXT_ERR_WINDOWS); break;
		}
	}
};

#endif //Error_h